<template>
  <div class="avatar-uploader">
    <div class="upload-box" @click="handleClick">
      <input
        ref="fileInput"
        type="file"
        accept="image/png, image/jpeg"
        @change="handleFileChange"
        style="display: none;"
      />
      <img v-if="imageUrl" :src="imageUrl" alt="头像" class="avatar-preview" />
      <div v-else class="upload-placeholder">+</div>
    </div>
  </div>
</template>

<script>
import { ref, watch } from "vue"
import { uploadAvatar } from "@/api/upload.js"
import {Message} from "@arco-design/web-vue"

export default {
  name: "AvatarUploader",
  props: {
    modelValue: {
      type: String,
      default: "",
    },
  },
  emits: ["update:modelValue"],
  setup(props, { emit, expose }) {
    const imageUrl = ref(props.modelValue); // 初始值
    const fileInput = ref(null); // 文件输入框引用
    const selectedFile = ref(null); // 当前选择的文件

    // 更新父组件绑定的值
    watch(
      () => props.modelValue,
      (newValue) => {
        imageUrl.value = newValue; // 监听父组件初始值的变化
      },
      { immediate: true } // 确保初始值能立即生效
    );

    watch(imageUrl, (newValue) => {
      emit("update:modelValue", newValue); // 双向绑定
    });

    // 点击上传框触发文件选择
    const handleClick = () => {
      fileInput.value.click();
    };

    // 处理文件选择
    const handleFileChange = async (event) => {
      const file = event.target.files[0];
      if (!file) return;

      try {
        await validateImage(file); // 使用用户提供的校验规则
        const objectUrl = URL.createObjectURL(file); // 本地预览
        imageUrl.value = objectUrl;
        selectedFile.value = file; // 保存文件
      } catch (error) {
        console.log(error)
        clear(); // 校验失败清空
      }
    };

    // 校验规则（使用用户提供的 validateImage 函数）
    const validateImage = (file) => {
      const maxSize = 2 * 1024 * 1024; // 2MB
      const maxDimensions = 1024;
      const allowedTypes = ["image/png", "image/jpeg"];

      return new Promise((resolve, reject) => {
        if (!allowedTypes.includes(file.type)) {
          Message.error("只支持png和jpg格式的图片");
          reject(new Error("InvalidFileType"));
          return;
        }

        if (file.size > maxSize) {
          Message.error("图片大小不能超过2MB");
          reject(new Error("FileSizeExceeded"));
          return;
        }

        const img = new Image();
        const objectUrl = URL.createObjectURL(file);

        img.onload = () => {
          URL.revokeObjectURL(objectUrl); // 清除对象URL以释放内存
          if (img.width > maxDimensions || img.height > maxDimensions) {
            Message.error("图片尺寸不能超过1024x1024");
            reject(new Error("ImageDimensionsExceeded"));
          } else {
            resolve();
          }
        };

        img.onerror = () => {
          URL.revokeObjectURL(objectUrl);
          Message.error("图片加载失败");
          reject(new Error("ImageLoadError"));
        };

        img.src = objectUrl;
      });
    };

    // 上传方法
    const upload = async () => {
      if (!selectedFile.value) {
        Message.info("未选择图片");
        return;
      }

      const formData = new FormData();
      formData.append("file", selectedFile.value);

      try {
        const response = await uploadAvatar(formData);
        if (response.data) {
          imageUrl.value = response.data.data.url; // 假设返回的图片地址字段为 `url`
        }
      } catch (error) {
        Message.error("图片上传失败");
        console.log(error)
      }
    };

    // 清空方法
    const clear = () => {
      imageUrl.value = "";
      selectedFile.value = null;
      fileInput.value.value = ""; // 清空文件输入框
    };

    // 向外暴露方法
    expose({
      upload,
      clear,
    });

    return {
      imageUrl,
      fileInput,
      handleClick,
      handleFileChange,
    };
  },
};
</script>

<style scoped>
.upload-box {
  width: 150px;
  height: 150px;
  border: 2px dashed #d9d9d9;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 4px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.upload-box:hover {
  border-color: #409eff;
}

.upload-placeholder {
  font-size: 24px;
  color: #d9d9d9;
}

.avatar-preview {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
</style>
